#include "async_io.h"
#define SERVERPORT 8888
#define MAX_EVENTS 10
#define BUFFER_SIZE 1024

// 定义一个宏用于表示未使用的参数
#define UNUSED(x) (void)(x)
#include <arpa/inet.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <signal.h>
#include <unistd.h>

int server_fd;

char   buff[BUFFER_SIZE];
size_t size_buff = 0;

char   tcp_buff[BUFFER_SIZE];
size_t size_tcp_buff = 0;

static void app_destroy()
{
    // 关闭套接字
    async_exit();
    if (server_fd)
        close(server_fd);
}

int create_socket(const char *ip, int port)
{
    int server_fd = socket(AF_INET, SOCK_STREAM, 0);
    if (server_fd == -1) {
        perror("socket");
        return -1;
    }

    // 绑定和监听...
    struct sockaddr_in laddr;
    laddr.sin_family = AF_INET;
    laddr.sin_port   = htons(port);
    inet_pton(AF_INET, ip, &laddr.sin_addr);

    // 设置地址重用
    int optval = 1;
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1) {
        perror("setsockopt");
        exit(-1);
    }

    if (bind(server_fd, (struct sockaddr *)&laddr, sizeof(laddr)) < 0) {
        perror("bind");
        exit(-1);
    }

    if (listen(server_fd, 200) < 0) {
        perror("listen");
        exit(-1);
    }
    return server_fd;
}

static int client_write_callback(int fd, int write_size)
{
    UNUSED(fd);
    if (write_size > 0) {
        printf("write ok\n");
    }
    else {
        perror("write");
        return -1;
    }
    return 0;
}

static int client_callback(int fd, int read_size, void *data)
{
    if (read_size == 0) {
        printf("%d 断开链接\n", fd);
        close(fd);
        return -1;
    }

    if (read_size == -1) {
        printf("%d 断开链接, 错误\n", fd);
        close(fd);
        return -1;
    }

    printf("form %d read %d:%s\n", fd, read_size, (char *)data);

    // 写会客户端
    async_write(fd, tcp_buff, read_size, client_write_callback);
    memset(tcp_buff, 0, read_size);
    async_read(fd, tcp_buff, sizeof(tcp_buff), client_callback);
    return 0;
}

static int server_callback(int clean_fd, struct sockaddr_in client_addr)
{
    printf("New connection from %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

    async_read(clean_fd, tcp_buff, sizeof(tcp_buff), client_callback);
    async_accept(server_fd, server_callback);
    return 0;
}

int main()
{
    atexit(app_destroy);

    async_init();
    server_fd = create_socket("0.0.0.0", SERVERPORT);
    async_accept(server_fd, server_callback);
    async_exec();

    return 0;
}
